package com.platform.destiny.utils;


import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.platform.destiny.common.Constant;
import com.platform.destiny.dto.UserDto;
import com.platform.destiny.exception.AppException;
import com.platform.destiny.exception.RetCode;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtUtils {

    private final static String secret = "654321";

    public static void main(String[] args) {

        UserDto dto = new UserDto();
        dto.setUsername("admin");
        dto.setEnabled(true);
        dto.setId(234L);
        String token = createToken(dto);
        System.out.println(token);
        UserDto dto1 = parseToken(token);
        System.out.println(dto1);


    }
    /**
     * 创建 token
     */
    public static String createToken(UserDto dto) {
        String token = Jwts.builder()
                //  主题 放入用户名
                .setSubject(dto.getUsername())
                .claim("username", dto.getUsername())
                .claim("authorities", dto.getAuthorities())
                .claim("status", dto.getEnabled())
                .claim("id", dto.getId())
                .claim("data", JSONObject.toJSONString(dto))
                .setIssuer("123456@163.com")
                .setIssuedAt(new DateTime())
                .setId(IdUtil.fastSimpleUUID())
                // 失效时间
                .setExpiration(DateUtil.offset(new DateTime(), DateField.HOUR, 48))
                // 签名算法和密钥 HS512 对称加密 RS256 非对称加密
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
        log.info("token is {}", token);
        return Constant.token_prefix + token;
    }






















    /**
     * 解析 token
     */
    public static UserDto parseToken(String token) {

        Claims claims = getTokenBody(token);
        Date expiration = claims.getExpiration();
        if(!new DateTime().isBefore(expiration)){
            throw new AppException(RetCode.EXPIRATION);
        }
        log.info("claims is {}", claims);
        String subject = claims.getSubject();
        Object username = claims.get("username");
        log.info("subject is {} and username is {}", subject, username);
        String tmp = claims.get("data").toString();
        return JSONObject.parseObject(tmp, UserDto.class);
    }


















    private static Claims getTokenBody(String token) {
        token = (StrUtil.subSuf(token, Constant.token_prefix.length()));
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token).getBody();
    }

    public static boolean isExpiration(String token){
        Date expiration = getTokenBody(token).getExpiration();
        // 当前时间在过期时间之前即有效 否则即失效
        return !new DateTime().isBefore(expiration);
    }







}
